package com.smp.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author sun.yonghui
 * @date 2020/9/18
 */
public class DateUtils {
    private DateUtils() {
    }

    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DATE_PATTERN_2 = "yyyy/MM/dd";
    public static final String DATE_PATTERN_3 = "yyyyMMdd";
    public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String TIME_PATTERN_MINUTE = "HH:mm";
    public static final String SPLASH = "-";
    public static final String SLANTING = "/";

    public static Date stringToDate(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        return stringToDate(str, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date stringToDate(String str, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            Date d = sdf.parse(str);
            return d;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new Date();
    }

    /**
     * 将字符串转换为LocalDate, 如果不正常则返回null, 不抛异常
     *
     * @param str
     * @return
     */
    public static LocalDate valueOf(String str) {
        if (StringUtils.contains(str, SPLASH)) {
            return DateUtils.valueOf(str, DateUtils.DATE_PATTERN);
        } else if (StringUtils.contains(str, SLANTING)) {
            return DateUtils.valueOf(str, DateUtils.DATE_PATTERN_2);
        }
        return null;
    }

    public static LocalDate valueOf(String str, String pattern) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        if (StringUtils.isEmpty(pattern)) {
            return null;
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        try {
            return LocalDate.parse(str, dateTimeFormatter);
        } catch (Exception ex) {
            return null;
        }
    }

    public static String toDayString(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        return year + "年" + month + "月" + day + "日";
    }

    public static String toDayString(Date date, String separationStr) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);

        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        return year + separationStr + month + separationStr + day;
    }

    public static String dayString(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH) + 1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        return month + "月" + day + "日";
    }

    public static String format(LocalDateTime localDateTime, String pattern) {
        if (Objects.isNull(localDateTime)) {
            return StringUtils.EMPTY;
        }
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String format(LocalDateTime localDateTime) {
        return format(localDateTime, DEFAULT_DATETIME_PATTERN);
    }

    public static String format(LocalDate localDate, String pattern) {
        if (Objects.isNull(localDate)) {
            return StringUtils.EMPTY;
        }
        return localDate.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String format(LocalDate localDate) {
        return format(localDate, DATE_PATTERN);
    }

    public static String dateFormatDay(Date date) {
        return DateFormatUtils.format(date.getTime(), DATE_PATTERN);
    }

    public static String defaultDateFormatDay(Date date) {
        return DateFormatUtils.format(date.getTime(), DEFAULT_DATETIME_PATTERN);
    }

    public static String dateFormatTimeMinute(Date date) {
        return DateFormatUtils.format(date.getTime(), TIME_PATTERN_MINUTE);
    }



    public static List dayFromDay(String startTime, String endTime) {
        // 返回的日期集合
        List<String> days = new ArrayList<>();

        DateFormat dateFormat = new SimpleDateFormat(DATE_PATTERN);
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            // 日期加1(包含结束)
            tempEnd.add(Calendar.DATE, +1);
            DateFormat reDateFormat = new SimpleDateFormat("MM月dd日");
            while (tempStart.before(tempEnd)) {
                days.add(reDateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            return new ArrayList();
        }

        return days;
    }

    public static List dayFromatWeek(String startTime, String endTime) {
        String startYear = startTime.substring(0, 4);
        String startWeek = startTime.substring(4, 6);
        String endYear = endTime.substring(0, 4);
        String endWeek = endTime.substring(4, 6);
        List<String> sWeek = new ArrayList<>();

        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.YEAR, Integer.valueOf(startYear));
        cal.set(Calendar.MONTH, 11);
        cal.set(Calendar.DATE, 31);

        Integer week = 0;
        String weekStr = "";
        //同一年
        if (startYear.equals(endYear)) {
            for (int i = 0; i <= (Integer.valueOf(endWeek) - Integer.valueOf(startWeek)); i++) {
                week = Integer.valueOf(startWeek) + i;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }
                sWeek.add(startYear + "年" + weekStr + "周");
            }
        } else {

            //第一年
            for (int i = 0; i <= (cal.getWeeksInWeekYear() - Integer.valueOf(startWeek)); i++) {
                week = Integer.valueOf(startWeek) + i;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }
                sWeek.add(startYear + "年" + weekStr + "周");
            }

            for (int i = Integer.parseInt(endWeek); i > 0; i--) {
                week = Integer.valueOf(endWeek) - i + 1;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }
                sWeek.add(endYear + "年" + weekStr + "周");
                if (i == 1) {
                    break;
                }
            }
        }
        return sWeek;
    }

    public static List dayFromatMon(String startTime, String endTime) {
        String startYear = startTime.substring(0, 4);
        String startMon = startTime.substring(4, 6);
        String endYear = endTime.substring(0, 4);
        String endMon = endTime.substring(4, 6);
        List<String> sWeek = new ArrayList<>();

        Calendar cal = Calendar.getInstance();
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.YEAR, Integer.valueOf(startYear));
        cal.set(Calendar.MONTH, 11);
        cal.set(Calendar.DATE, 31);

        Integer week = 0;
        String weekStr = "";
        //同一年
        if (startYear.equals(endYear)) {
            for (int i = 0; i <= (Integer.valueOf(endMon) - Integer.valueOf(startMon)); i++) {
                week = Integer.valueOf(startMon) + i;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }

                sWeek.add(startYear + "年" + weekStr + "月");
            }
        } else {
            int yearMonth = 12;

            //第一年
            for (int i = 0; i <= (yearMonth - Integer.valueOf(startMon)); i++) {
                week = Integer.valueOf(startMon) + i;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }
                sWeek.add(startYear + "年" + weekStr + "月");
            }
            //相隔几年
            if (1 < (Integer.valueOf(endYear) - Integer.valueOf(startYear))) {
                for (int index = 1; index <= (Integer.valueOf(endYear) - Integer.valueOf(startYear) - 1); index++) {
                    for (int i = 1; i <= yearMonth; i++) {
                        week = i;
                        if (week < 10) {
                            weekStr = "0" + week;
                        } else {
                            weekStr = week + "";
                        }
                        sWeek.add(Integer.valueOf(startYear) + index + "年" + weekStr + "月");
                    }
                }
            }

            for (int i = Integer.parseInt(endMon); i > 0; i--) {
                week = Integer.valueOf(endMon) - i + 1;
                if (week < 10) {
                    weekStr = "0" + week;
                } else {
                    weekStr = week + "";
                }
                sWeek.add(endYear + "年" + weekStr + "月");
                if (i == 1) {
                    break;
                }
            }
        }
        return sWeek;
    }

    public static LocalDateTime convert(Date date) {
        return convert(date, DEFAULT_DATETIME_PATTERN);
    }

    public static LocalDateTime convert(Date date, String pattern) {

        if (date == null) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return LocalDateTime.parse(simpleDateFormat.format(date), DateTimeFormatter.ofPattern(pattern));
    }

    public static Boolean isToday(LocalDateTime dateTime) {
        if (Objects.isNull(dateTime)) {
            return false;
        }
        return dateTime.toLocalDate().equals(LocalDate.now());
    }

    public static String secondToHourMinute(Long seconds) {
        String empty = "-";
        if (seconds == null) {
            return empty;
        }
        StringBuilder result = new StringBuilder();
        long hour = seconds / 3600;
        long minute = seconds % 3600 / 60;
        if (hour > 0) {
            result.append(hour).append("小时");
        }
        if (minute > 0) {
            result.append(minute).append("分钟");
        }
        return StringUtils.isEmpty(result.toString()) ? empty : result.toString();
    }

    /**
     * 解析时间字符串 类似 2.01704031349E13
     *
     * @param dateString 传入一个时间段字符串
     * @return 格式正确则返回对应的java.util.Date对象 格式错误返回null
     */
    public static Date bigDecimalStringDate2Date(String dateString) {
        try {
            // 科学计数法数据转为字符串
            BigDecimal bd = new BigDecimal(dateString);
            dateString = bd.toPlainString();

            long milliSecond = Long.valueOf(dateString);

            Date date = new Date();
            date.setTime(milliSecond);
            return date;
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * map转String
     *
     * @param map
     * @return
     */
    public static String mapToString(Map map) {
        try {
            JSONObject json = new JSONObject(map);
            return json.toString();
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 日期的加减方法
     * 用于在当前的天加上或者减去若干日
     * @param currdate 当前日期
     * @param day 天数，
     * @return 返回加上或者减去的那个日期
     */
    public static Date dayAddAndSub(Date currdate,int day) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(currdate);
        ca.add(Calendar.DATE, day);
        return ca.getTime();
    }

    /**
     * LocalDateTime -> Date
     * @param localDateTime localDateTime
     * @return Date
     */
    public static Date asDate(LocalDateTime localDateTime) {
        if (null == localDateTime) {
            return null;
        }
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取当前日期
     * @return
     */
    public static String getCurrentTime(){
        LocalDate currentTime = LocalDate.now();
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00");
        return currentTime.format(fmt);
    }

}
